package demo04

/**
 * @author xiaoZhao
 * @date 2022/6/29
 * @describe 闭包 : 内层函数用到了外层函数里面的局部变量或着一个参数
 *           为了在调用时分层调用，第二层还能够访问到外层的变量，需要将外层的局部变量和内层的函数打包在一起
 *           保存在一个函数的对象实例中，存储在jvm堆内存中。
 *
 *           柯里化：
 */
object Test09_ClouseAndCurrying {
  def main(args: Array[String]): Unit = {
    def add(a: Int, b: Int): Int = {
      a + b
    }

    // 1.考虑固定一个加数的场景
    def addByFour(b: Int): Int = {
      4 + b
    }

    // 2. 扩展固定加数改变
    def addByFive(b: Int): Int = {
      5 + b
    }

    // 3.将固定加数作为另一个参数传入，但是作为“第一层”参数传入
    def addByFour1(): Int => Int = {
      val a = 4

      def addB(b: Int): Int = {
        a + b
      }

      addB
    }

    def addByA(a: Int): Int => Int = {
      def addB(b: Int): Int = {
        a + b
      }
      addB
    }

    println(addByA(12)(23))

    // 简化
    def addByA1(a: Int): Int => Int = {
      (b: Int) => {
        a + b
      }
    }

    def addByA2(a: Int): Int => Int = {
      b => {
        a + b
      }
    }

    def addByA3(a: Int): Int => Int = {
      b => a + b
    }

    def addByA4(a: Int): Int => Int = {
      a + _
    }

    def addByA5(a: Int): Int => Int = a + _

    // 柯里化 Currying
    def addCurrying(a: Int)(b: Int): Int = a + b

    println(addCurrying(21)(23))

  }
}
